/*
 * PBoostSocketClient.h
 *
 *  Created on: May 20, 2014
 *      Author: yuliang
 */

#ifndef PBOOSTSOCKETCLIENT_H_
#define PBOOSTSOCKETCLIENT_H_

#include <stdint.h>
#include <string>

//#include <boost/asio.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/asio/basic_stream_socket.hpp>
#include <boost/bind.hpp>

#include "PBoostSocketBase.h"
#include "PMemoryPool.h"
#include "PSingleton.h"

using namespace boost::asio;
using namespace boost::asio::ip;
using namespace boost::system;

#define PKG_HEADER_LEN							4
#define PKG_MAX_LEN								0xFFFF0000
#define TCP_MEMPOOL_DEFUALT_SIZE				5

#ifndef LOG4CPLUS_TCP_SOCKET
#define LOG4CPLUS_TCP_SOCKET					"logTcpSocket"
#else
#error "LOG4CPLUS_TCP_SOCKET is def."
#endif

/*
 * CTcpClientCallbackBase	: client sock回调纯虚基类
 * CTcpClient				: client sock操作纯虚基类, 继承CTcpClientCallBackBase
 * CTcpConnectClient		: connect client sock 操作纯虚基类, 继承CTcpClient
 * 							  用于创建一个client连接service, 并进行通信;
 * 							  如需分包, 在OnReceive进行分包.
 * 							  外部方法: Connect 连接service
 * 							           SendData 向service端发送数据(异步)
 * 							  如需使用, 则继承此类, 重载回调基类的方法(无特殊情况则继承原访问权限);
 */

class CTcpClient : protected CClientCallbackBase {
protected:
	class CMemoryPoolObject {
	public:
		CMemoryPoolObject() : m_MemPool(new CPMemoryPool) {}
		~CMemoryPoolObject() {}
		inline void Init(uint32_t maxBufSize) { m_MemPool->Init(maxBufSize, TCP_MEMPOOL_DEFUALT_SIZE); }
		inline CPMemoryPool* GetMemoryPool() { return m_MemPool; }
	private:
		CPMemoryPool* m_MemPool;
	};
public:
	CTcpClient(io_service& ioservice, uint32_t maxBufSize);
	virtual ~CTcpClient();
	void SendData(const char *buf, uint32_t len);
	void SendLenAndData(const char *buf, uint32_t len);
	inline void DeleteClient() { closeSession(); if (!m_SendFlag) delete this; }
	inline tcp::socket& GetSocket() { return m_Socket; }
	inline void Close() { closeSession(); }
	inline void SetUserData(void* data) { m_UserData = data; }
	inline void* GetUserData() const { return m_UserData; }
protected:
	void start();
	inline void closeSession() { if (m_Socket.is_open()) m_Socket.close(); }
private:
	void handle_read(const error_code& error, std::size_t buflen);
	void handle_write(const error_code& error, std::size_t, const char *buf, uint32_t len);
private:
	tcp::socket m_Socket;
	char *m_Data;
	uint32_t m_SendFlag;
	void* m_UserData;
};

class CTcpConnectClient : public CTcpClient {
public:
	CTcpConnectClient(io_service& ioservice, uint32_t maxBufSize);
	virtual ~CTcpConnectClient();
	bool Connect(const std::string &ip, uint16_t port);
};

#endif /* PBOOSTSOCKETCLIENT_H_ */
